﻿using EarthGrid.core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using OSGeo.OGR;
using EarthGrid.shp;
using System.IO;
using EarthGrid.log;
using System.Collections;

namespace EarthGrid.app
{
    public class Class1
    {
        GridShpTool gridShpTool;

        public Class1(string filePath)
        {
            this.gridShpTool = new GridShpTool(filePath, wkbGeometryType.wkbPolygon);
        }
        
        List<Feature> features = new List<Feature>();
        ICollection<Feature> fsList = new List<Feature>();
        public async ValueTask createGrids(int level, int threadsCount)
        {
            using (SemaphoreSlim semaphoreSlim = new SemaphoreSlim(threadsCount))
            {
                List<Task> tasks = new List<Task>();
                await semaphoreSlim.WaitAsync();
                tasks.Add(Task.Run(() =>
                {
                    sd(GridTool.createGridFromParent(Grid.FirstLevelGridG0,false), level);
                }));
                tasks.Add(Task.Run(() =>
                {
                    sd(GridTool.createGridFromParent(Grid.FirstLevelGridG1, false), level);
                }));
                tasks.Add(Task.Run(() =>
                {
                    sd(GridTool.createGridFromParent(Grid.FirstLevelGridG2, false), level);
                }));
                tasks.Add(Task.Run(() =>
                {
                    sd(GridTool.createGridFromParent(Grid.FirstLevelGridG3, false), level);
                }));
                tasks.Add(Task.Run(() =>
                {
                    分割南北极网格(level, gridShpTool);
                }));

                await Task.WhenAll(tasks);
                foreach (Task task in tasks) task.Dispose();
            }
            gridShpTool.ExportFeatures(fsList as List<Feature>);
        }

        public async ValueTask createGrids(int minx, int miny, int maxx, int maxy, int level, int threadsCount)
        {
            using (SemaphoreSlim semaphoreSlim = new SemaphoreSlim(threadsCount))
            {
                List<Task> tasks = new List<Task>();
                await semaphoreSlim.WaitAsync();
                tasks.Add(Task.Run(() =>
                {
                    根据范围分(new Grid[1] {
                        Grid.FirstLevelGridG0
                        /*Grid.FirstLevelGridG1,
                        Grid.FirstLevelGridG2,
                        Grid.FirstLevelGridG3*/
                    }, level,minx, miny, maxx, maxy);
                }));
                /*tasks.Add(Task.Run(() =>
                {
                    分割南北极网格(level, gridShpTool);
                }));*/
                
                await Task.WhenAll(tasks);
                gridShpTool.ExportFeatures(features);
            }
        }

        private void 根据范围分(Grid[] grids, int level, int minx, int miny, int maxx, int maxy)
        {
            if (null == grids) return;
            for (int i = 0; i < grids.Length; i++)
            {
                Grid g = grids[i];
                if (g.Level > level)
                {
                    return;
                }
                if (g.MinLon.Du > maxx) continue;
                if (g.MaxLon.Du < minx) continue;
                if (g.MinLat.Du > maxy) continue;
                if (g.MaxLat.Du < miny) continue;

                if (!g.是否有效())
                {
                    continue;
                }
                // 
                if (g.Level == 8 && (g.MinLat.Du >= 88 || g.MaxLat.Du <= -88))
                {
                    continue;
                }
                // 临时写入shp文件
                Feature f = gridShpTool.CreateFeature(g);
                features.Add(f);
                if (features.Count > 2000)
                {
                    gridShpTool.ExportFeatures(features);
                    features.Clear();
                   // Log.InfoAsync("写入shp");
                }
                if (g.Level < level)
                    根据范围分(GridTool.createGridFromParent(g, false), level, minx, miny, maxx, maxy);
            }
        }

        private void sd(Grid[] grids, int level)
        {
            if (null == grids) return;
            for (int i = 0; i < grids.Length; i++)
            {
                Grid g = grids[i];
                if (g.Level > level)
                {
                    return;
                }
                if (!g.是否有效())
                {
                    continue;
                }
                // 
                if (g.Level == 8 && (g.MinLat.Du >= 88 || g.MaxLat.Du <= -88))
                {
                    continue;
                }
                // 临时写入shp文件
                Feature f = gridShpTool.CreateFeature(g);
                lock (fsList)
                {
                   fsList.Add(f);
                    if (fsList.Count > 2000)
                    {
                        gridShpTool.ExportFeatures(fsList as List<Feature>);
                        fsList.Clear();
                        //Log.InfoAsync("写入shp");
                    }
                }
                if(g.Level < level)
                    sd(GridTool.createGridFromParent(g, false), level);
            }
        }

        /// <summary>
        /// 从第8级已初始化好的网格开始分割
        /// </summary>
        /// <param name="level"></param>
        /// <param name="shpTool"></param>
        private async void 分割南北极网格(int level, GridShpTool shpTool)
        {
            Grid[] gs_8 = GridTool.CreateLevel8GridLat88to90();
            await saveGrid(gs_8, shpTool);
            P0分割(GridTool.南北极四分法(gs_8[0]), level, shpTool);
            P0分割(GridTool.南北极四分法(gs_8[1]), level, shpTool);
        }
        
        private async void P0分割(Grid[] gs, int level, GridShpTool shpTool)
        {
            // 先保存这四个网格
            await saveGrid(gs, shpTool);

            if (gs[0].Level >= level)
                return;
            
            // 取第0个，用 南北极四分法
            P0分割(GridTool.南北极四分法(gs[0]), level, shpTool);

            // 取第2个，用 南北极P2跨正负的四分法
            Grid[] gs_wai = GridTool.南北极P2跨正负的四分法(gs[2]);
            P外层分割Async(gs_wai, level, shpTool);

            // 取第1和第3个,用 南北极P1P3的四分法
            Grid[] gs_dong = GridTool.南北极P1P3的四分法(gs[1]);
            Grid[] gs_xi = GridTool.南北极P1P3的四分法(gs[3]);
            P外层分割Async(gs_dong, level, shpTool);
            P外层分割Async(gs_xi, level, shpTool);
        }

        private async void P外层分割Async(Grid[] gs, int level, GridShpTool shpTool)
        {
            // 先保存网格
            await saveGrid(gs, shpTool);
            if (gs[0].Level >= level) return;
            for (int i = 0; i < gs.Length; i++)
            {
                if (gs[i].是否有效())
                    P外层分割Async(GridTool.南北极10级以下外层分法(gs[i]), level, shpTool);
            }
        }

        private async Task saveGrid(Grid[] gs, GridShpTool shpTool)
        {
            for (int i = 0; i <gs.Length; i++)
            {
                if (gs[i].是否有效())
                {
                    Feature f = shpTool.CreateFeature(gs[i]);
                    fsList.Add(f);
                }
            }
            if (features.Count > 20000)
            {
                shpTool.ExportFeatures(fsList as List<Feature>);
                fsList.Clear();
                Log.InfoAsync("写入shp");
            }
        }
    }
}
